package IC.SymbolTable;

import java.util.HashMap;
import java.util.LinkedHashMap;

import IC.Constants;
import IC.SemanticChecks.SemanticError;
import IC.SemanticChecks.SemanticErrorType;


public class ExtendingClassSymbolTable extends RecursiveLookupSymbolTable {

	private LinkedHashMap<String,Symbol> Fields;
	private LinkedHashMap<String,Symbol> StaticMethods;
	private LinkedHashMap<String,Symbol> VirtualMethods;
	private SymbolTable BaseClassSymbolTable;
	
	//C'tor
	public ExtendingClassSymbolTable(String id, SymbolTable superClass) {
		super(id,id);
		Fields = new LinkedHashMap<String,Symbol>();
		StaticMethods = new LinkedHashMap<String,Symbol>();
		VirtualMethods = new LinkedHashMap<String,Symbol>();
		this.BaseClassSymbolTable = superClass;
	}

	public SymbolTable getSuperClassSymbolTable() {
		return BaseClassSymbolTable;
	}

	@Override
	public Symbol getValue(String id) {
		if (Fields.containsKey(id)) {
			return Fields.get(id);
		} else if (StaticMethods.containsKey(id)) {
			return StaticMethods.get(id);
		} else {
			return VirtualMethods.get(id);
		}
	}

	@Override
	protected HashMap<String, Symbol> getInnerHashMap(SymbolKind kind, int lineNumber) throws SemanticError {
		switch (kind) {
		case FIELD:
		case THIS:
			return Fields;
		case STATIC_METHOD:
			return StaticMethods;
		case VIRTUAL_METHOD:
			return VirtualMethods;
		default:
			throw new SemanticError(SemanticErrorType.INVALID_KIND, lineNumber);
		}
	}
	
	@Override
	public Symbol staticLookup(String id) {
		Symbol symbol = lookup(id);
		if (symbol == null)
			return null;
		switch (symbol.getKind()) {
		case STATIC_METHOD:
			return symbol;
		default:
			return null;
		}
	}
	
	@Override
	public Symbol virtualLookup(String id) {
		Symbol symbol = lookup(id);
		if (symbol == null) 
			return null;
		switch (symbol.getKind()) {
		case VIRTUAL_METHOD:
		case FIELD:
		case THIS:
			return symbol;
		default:
			return null;
		}
	}
		
	@Override
	public String toString() {
		String str = Title() + Constants.LINE_BREAK;
		
		for (Symbol symbol : Fields.values()) 
			if (symbol.getKind() != SymbolKind.THIS) 
				str += Constants.SPACE + symbol + Constants.LINE_BREAK;	
		
		for (Symbol symbol : StaticMethods.values()) 
			str += Constants.SPACE + symbol + Constants.LINE_BREAK;	
		
		for (Symbol symbol : VirtualMethods.values()) 
			str += Constants.SPACE + symbol + Constants.LINE_BREAK;	
		
		str += childrensToString();
		return str;
	}

	@Override
	public String Title() {
		return "Class Symbol Table: " + getDisplayId();
	}

}
